package com.tool.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

//import com.jp.entity.Bean;
//import com.jp.entity.Student;
//import com.jp.model.StudentModel;
/**
 * 
* @author dinghao
* @ClassName: ToBeanUtils 
* @Description: TODO
* @date 2018年3月16日 下午2:19:38 
*
 */
public class ToBeanUtils {
	
//	public static void main(String[] args) {
//		Student stu = new Student();
//		StudentModel stuModel = new StudentModel();
//		stu.setId("1001");
//		stu.setName("张三");
//		stu.setAge(18);;
//		stu.setSex("男");
//		stu.setClassId("三年级一班");
//		stu.setDel(true);
//		StudentModel studentModel = bean2Model(stu,stuModel.getClass());
//		Student student = bean2Model(stu, Student.class);
//		System.out.println(studentModel);
//		System.out.println(student);
//		
//		Map<String,String[]> map = new HashMap<String,String[]>();
//		map.put("id", new String[]{"1001"});
//		map.put("time",new String[]{"2017-11-21"} );
//		Bean bean = mapToBean(map,Bean.class);
//		System.out.println(bean);
//	}
	
	/**
	 * 将bean对象中的属性封装到model对象中
	 * @param bean  bean对象
	 * @param modelClz  model的类型
	 * @return
	 */
	public static <M,B> M bean2Model(B bean,Class<M> modelClz){
		Class<? extends Object> beanClz = bean.getClass();
		M model = null;
		try {
			model = modelClz.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		Field[] beanDeclaredFields = beanClz.getDeclaredFields();
		Field[] modelDeclaredFields = modelClz.getDeclaredFields();
		for(Field field : beanDeclaredFields) {
			if(fieldIsModelField(field,modelDeclaredFields)) {
				String fieldName = field.getName();
				//拼接属性的set方法
				String setMethodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
				//拼接属性的get方法
				try {
					String getMethodName = null;
					//判断该属性的类型是否为boolean类
					if(modelClz.getDeclaredField(fieldName).getType().toString().equals("boolean")) {
						//如果是boolean构建is方法
						getMethodName = "is"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
					}else {
						//如果不是构建get方法
						getMethodName = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
					}
					//根据方法名反射方法
					Method setMethod = modelClz.getMethod(setMethodName, modelClz.getDeclaredField(fieldName).getType());
					Method getMethod = beanClz.getMethod(getMethodName);
					//掉 用setter方法
					setMethod.invoke(model, getMethod.invoke(bean));
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		return model;
	}
	
	/**
	 * 判断bean的属性是不是也是model的属性
	 * @param field  bean的属性
	 * @param modelDeclaredFields model的所有的属性
	 * @return
	 */
	private static boolean fieldIsModelField(Field field, Field[] modelDeclaredFields) {
		String name = field.getName();
		Class<?> type = field.getType();
		for (Field field1 : modelDeclaredFields) {
			if(field1.getName().equals(name) && field1.getType() == type){
				return true;
			}
		}
		return false;
	}

    /** 
     * 把map转化成对象 
     *  
     * @param map 
     * @param calzz 
     * @return  
     *  
     * 把Map转化成指定类型 (支持日期装换)
     */  
    public static <T> T mapToBean(Map map, Class<T> clazz) {  
        try {  
            /* 
             * 1.通过参数clazz创建实例 
             * 2.使用BeanUtils.populate把map的数据封闭到bean中 
             */  
            T bean = clazz.newInstance();  
            /* 
             * 自定义的类型转换器DateConverter() 
             * 1.第一个参数为自定义的转换器 
             * 2.第二个参数为目标类型 
             */  
            
            ConvertUtils.register(new DateConverter(),java.util.Date.class);  
            BeanUtils.populate(bean, map);  
            return bean;  
  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
	
	
	/**
	 * 将map装换为javaBean对象(不支持日期的转换)
	 * @param clz  JavaBean对象的类型
	 * @param parameterMap  map集合(map对象的key必须和JavaBean的属性名称保证一致)
	 * @return
	 */
	@SuppressWarnings("unused")
	private static <T> T map2Bean(Class<T> clz, Map<String, String[]> parameterMap) {
		ConvertUtils.register(new DateConverter(), java.util.Date.class);
		T obj = null;
		try {
			obj = (T) clz.newInstance();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		}
		Field[] fields = clz.getDeclaredFields();
		//key代表属性，Set<key> 属性名的集合
		Set<String> keySet = parameterMap.keySet();
		for (String key : keySet) {
			//判断key是否为Bean的属性
			if(isBeanField(key,fields)){
				//拼接属性的set方法
				String setMethodName = "set"+key.substring(0,1).toUpperCase()+key.substring(1);
				try {
					//根据方法名反射方法
					Method method = clz.getMethod(setMethodName, clz.getDeclaredField(key).getType());
					//掉 用setter方法
					method.invoke(obj, TypeUtils.getValue(method.getParameterTypes()[0].getName(), parameterMap.get(key)[0]));
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		return obj;
	}

	/**
	 * 判断map的key是不是JavaBean的属性
	 * @param key  map的key
	 * @param fields  JavaBean的属性数组
	 * @return
	 */
	private static boolean isBeanField(String key, Field[] fields) {
		for (Field field : fields) {
			if(field.getName().equals(key)){
				return true;
			}
		}
		return false;
	}

}
